#pragma once

#include "MasterList.hpp"
#include <iostream>
#include <cstdlib>

typedef int ElemType;

const ElemType Default = 0;

typedef struct LNode {
    ElemType data;
    struct LNode* next;
} LNode, *LinkList;

class LinkListC : public MasterList<LinkList, ElemType> {
private:
    LinkList temp;

public:
    Status initList(LinkList& l) override
    {
        l = new LNode;
        l->next = nullptr;
        return Status::Ok;
    }

    Status destoryList(LinkList& l) override
    {
        while (l != nullptr) {
            temp = l;
            l = l->next;
            delete temp;
        }
        return Status::Ok;
    }

    Status clearList(LinkList& l) override
    {
        temp = l;
        while (l != nullptr) {
            l->data = Default;
            l = l->next;
        }
        l = temp;
        return Status::Ok;
    }

    bool listEmpty(const LinkList l) override
    {
        return l == nullptr || l->next == nullptr;
    }

    int listLength(const LinkList l) override
    {
        if (l == nullptr)
            return Status::Err;
        int count = 0;
        temp = l;
        while (temp != nullptr) {
            temp = temp->next;
            count++;
        }
        return count;
    }

    Status getElem(const LinkList l, int i, ElemType& e) override
    {
        if (l == nullptr || i < 0 || i > listLength(l))
            return Status::Err;
        int count = 0;
        temp = l;
        while (temp != nullptr) {
            if (count == i) {
                e = temp->data;
            }
            count++;
            temp = temp->next;
        }
        return Status::Ok;
    }

    int locateElem(const LinkList l, const ElemType e) override
    {
        if (l == nullptr)
            return Status::Err;
        int count = 0;
        temp = l;
        while (temp != nullptr) {
            if (temp->data == e) {
                return count;
            }
            count++;
            temp = temp->next;
        }
        return Status::Ok;
    }

    Status priorElem(const LinkList l, const ElemType cur_e, ElemType& pre_e) override
    {
        if (l == nullptr)
            return Status::Err;
        temp = l;
        while (temp->next != nullptr) {
            if (temp->next->data == cur_e) {
                pre_e = temp->data;
            }
            temp = temp->next;
        }
        return Status::Ok;
    }

    Status nextElem(const LinkList l, const ElemType cur_e, ElemType& next_e) override
    {
        if (l == nullptr)
            return Status::Err;
        temp = l;
        while (temp->next != nullptr) {
            if (temp->data == cur_e) {
                next_e = temp->next->data;
            }
            temp = temp->next;
        }
        return Status::Ok;
    }

    Status listInsert(LinkList& l, int i, ElemType e) override
    {
        if (l == nullptr || i < 0 || i > listLength(l))
            return Status::Err;

        LinkList VLNode = new LNode;
        VLNode->next = l;
        int count = 0;
        temp = VLNode;
        while (temp->next != nullptr) {
            if (count == i) {
                LinkList mark = temp->next;
                temp->next = new LNode;
                temp->next->data = e;
                temp->next->next = mark;
                delete VLNode;
                return Status::Ok;
            }
            count++;
            temp = temp->next;
        }
        return Status::Err;
    }

    Status listDelete(LinkList& l, int i) override
    {
        if (l == nullptr || i < 0 || i > listLength(l))
            return Status::Err;

        LinkList VLNode = new LNode;
        VLNode->next = l;
        int count;
        temp = VLNode;
        while (temp->next != nullptr) {
            if (count == i) {
                LinkList mark = temp->next;
                temp->next = temp->next->next;
                delete mark;
                delete VLNode;
                return Status::Ok;
            }
            count++;
            temp = temp->next;
        }
        return Status::Err;
    }

    Status traverseList(const LinkList l) override
    {
        if (l == nullptr)
            return Status::Err;
        temp = l;
        while (temp != nullptr) {
            std::cout << temp->data << std::endl;
            temp = temp->next;
        }
        return Status::Ok;
    }
};
